package cn.com.bluemoon.daps.system.controller;


import cn.com.bluemoon.daps.api.model.RemoteDapDataModelSystemTagMiddleService;
import cn.com.bluemoon.daps.api.model.RemoteDataModelService;
import cn.com.bluemoon.daps.common.datascope.BmPermission;
import cn.com.bluemoon.daps.common.datascope.log.OperateLog;
import cn.com.bluemoon.daps.common.datascope.log.enums.ModuleObject;
import cn.com.bluemoon.daps.common.datascope.log.enums.OperateType;
import cn.com.bluemoon.daps.common.datascope.log.holder.ProcessLogHolder;
import cn.com.bluemoon.daps.common.domain.BaseModel;
import cn.com.bluemoon.daps.common.domain.ResultBean;
import cn.com.bluemoon.daps.common.domain.UserInfoHolder;
import cn.com.bluemoon.daps.common.enums.BmStatus;
import cn.com.bluemoon.daps.common.enums.DatabaseType;
import cn.com.bluemoon.daps.domp.api.IDompService;
import cn.com.bluemoon.daps.domp.api.LocalDompService;
import cn.com.bluemoon.daps.domp.api.param.UserDto;
import cn.com.bluemoon.daps.model.entity.DapDataModel;
import cn.com.bluemoon.daps.model.entity.DapDataModelSystemTagMiddle;
import cn.com.bluemoon.daps.system.dto.SysInfoDto;
import cn.com.bluemoon.daps.system.dto.SystemInfoDto;
import cn.com.bluemoon.daps.system.entity.*;
import cn.com.bluemoon.daps.system.service.*;
import cn.com.bluemoon.daps.system.service.impl.LocalDompServiceImpl;
import cn.com.bluemoon.daps.system.vo.SystemInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import javax.validation.constraints.Size;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 系统数据源表 前端控制器
 * </p>
 *
 * @author admin
 * @since 2020-08-04
 */


@RestController
@Slf4j
@RequestMapping("/dapSystem")
@Api(tags = {"系统管理"})
@Validated
public class DapSystemController {

    @Resource
    DapSystemDatasourceService dapSystemDatasourceService;

    @Resource
    DapSystemTagService dapSystemTagService;

    @Resource
    DapSystemInfoService dapSystemInfoService;

    @Resource
    RemoteDataModelService dapDataModelService;

    @Resource
    RemoteDapDataModelSystemTagMiddleService dapDataModelSystemTagMiddleService;

    @Resource
    LocalDompServiceImpl iDompService;

    @Resource
    DapSystemTagGroupService dapSystemTagGroupService;


    // v1.2 ok
    @BmPermission(value = "system:database:list", name = "列表查询")
    @GetMapping("datasource/all")
    @ApiOperation(value = "系统引用数据源，查询所有未被其他系统引用的数据源信息")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = DapSystemDatasource.class)})
    public ResultBean<List<DapSystemDatasource>> getAllDatasource(@RequestParam("sysType") String sysType){

        List<DapSystemDatasource> datasourceList = dapSystemDatasourceService.getAllDatasource("0");
        if(sysType.equals("WAREHOUSE_SYS")){
            // 过滤掉mysql数据源
            List<DapSystemDatasource> collect = datasourceList.stream()
                    .filter(d -> !d.getDatabaseType().equals(DatabaseType.MYSQL)).collect(Collectors.toList());
            return ResultBean.ok(collect);
        }
        return ResultBean.ok(datasourceList);
    }


    @BmPermission(value = {"model:info"}, name = "新建模型", ignore = true)
    @GetMapping("datasource/unUse")
    @ApiOperation(value = "新增模型的时候调用该接口，查询系统未被其他模型引用的数据源列表")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = DapSystemDatasource.class)})
    public ResultBean<List<DapSystemDatasource>> getDatasourceList(@RequestParam @ApiParam("系统id") String sysId){

        List<DapSystemDatasource> list = dapSystemDatasourceService.getBaseMapper()
                .selectList(new LambdaQueryWrapper<DapSystemDatasource>()
                .eq(DapSystemDatasource::getSystemInfoId, sysId));
        return ResultBean.ok(list);
    }

    // ok
    @BmPermission(value = "model:info", name = "新建模型",ignore = true)
    @GetMapping("datasource/category/type")
    @ApiOperation(value = "系统列表，新增模型的时候调用该接口，查询某个系统分类下的所有系统")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = DapSystemInfo.class)})
    public ResultBean<List<DapSystemInfo>> getSysCategoryList(@RequestParam @ApiParam(value = "系统分类, 1 :业务系统,2 :数仓系统,3 :数据产品,4 :其他", example = "0")
                                                                      Integer categoryType,
                                                              @RequestParam(required = false) @ApiParam(value = "模型id") String systemId){

        // 通过系统分类获得系统信息
        List<DapSystemInfo> list = dapSystemInfoService.getBaseMapper()
                .selectList(new LambdaQueryWrapper<DapSystemInfo>().eq(DapSystemInfo::getType, categoryType)
                .eq(DapSystemInfo::getBmStatus, BmStatus.ON.getCode()));
        // 为业务系统
        if(categoryType == 1){
            // 获得系统id列表
            List<String> ids = list.stream().map(DapSystemInfo::getId).collect(Collectors.toList());
            // 查询系统下绑定的模型
            if(!ids.isEmpty()){
                ResultBean<List<DapDataModel>> batchModel = dapDataModelService.getBatchModel(ids);
                if(null != batchModel.getContent()){
                    List<String> collect = batchModel.getContent().stream().map(DapDataModel::getSystemId)
                            .distinct().collect(Collectors.toList());
                    if(StringUtils.isNotEmpty(systemId)){
                        collect.remove(systemId);
                    }
                    // 未绑定的系统
                    List<DapSystemInfo> systemInfos = list.stream().filter(l -> !collect.contains(l.getId())).collect(Collectors.toList());
                    return ResultBean.ok(systemInfos);
                }
            }
        }
        return ResultBean.ok(list);
    }

    /**
     * 标签管理，搜索分页
     * @param pageSize
     * @param pageNum
     * @param key
     * @return
     */
    // ok
    @PostMapping("tags/pageList")
    @ApiOperation(value = "获取标签分页列表，带模糊搜索")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = ResultBean.class)})
    @BmPermission(value = "system:tags:list", name = "列表查询")
    @OperateLog(type = OperateType.SELECT, moduleName = ModuleObject.SYSTEM)
    public ResultBean<IPage<DapSystemTag>> selectTagsPage(@ApiParam(value ="每页显示的数量", example = "0") @RequestParam Integer pageSize,
                                                          @ApiParam(value = "当前页码数", example = "0") @RequestParam Integer pageNum,
                                                          @ApiParam("关键字") @RequestParam(required = false) String key,
                                                          @ApiParam("标签分组") @RequestParam(required = false) String  tagGroupId,
                                                          @ApiParam("标签类型") @RequestParam(required = false) Integer tagType){

        IPage<DapSystemTag> tagsPageList = dapSystemTagService.getTagsPageList(pageSize, pageNum, key, tagGroupId, tagType);
        ProcessLogHolder.append(String.format("共查询%s条数据\n", tagsPageList.getTotal()));
        ProcessLogHolder.append(String.format("  操作用户：%s", UserInfoHolder.getAccount()));
        return ResultBean.ok(tagsPageList);
    }

    @BmPermission(value = "system:tags:list", name = "标签详情")
    @GetMapping("tags/info")
    @ApiOperation(value = "标签详情")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = DapSystemTag.class)})
    public ResultBean<DapSystemTag> selectTag(@ApiParam(value ="标签id") @RequestParam("id") String id){

        DapSystemTag dapSystemTag = dapSystemTagService.getBaseMapper().selectById(id);
        return dapSystemTag == null ? ResultBean.error("标签不存在") : ResultBean.ok(dapSystemTag);
    }
    // ok
    @BmPermission(value = {"model:add","model:table:add","model:list"}, name = "标签列表", ignore = true)
    @PostMapping("tags/all")
    @ApiOperation(value = "获取标签全部列表")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = DapSystemTag.class)})
    public ResultBean<List<DapSystemTag>> getAllTagsPage(){

        List<DapSystemTag> dapSystemTags = dapSystemTagService.getBaseMapper()
                        .selectList(new LambdaQueryWrapper<DapSystemTag>()
                        .eq(DapSystemTag::getBmStatus, BmStatus.ON.getCode()));
        return ResultBean.ok(dapSystemTags);
    }
    // ok
    @BmPermission(value = "system:tags:add", name = "新增")
    @PostMapping("tags/insert")
    @ApiOperation(value = "新增标签")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = Boolean.class)})
    @OperateLog(type = OperateType.INSERT, moduleName = ModuleObject.SYSTEM)
    public ResultBean<Boolean> insertTags (@RequestBody @Valid DapSystemTag dapSystemTag){

        // 新增标签名先查询是否重名
        Boolean flag = dapSystemTagService.checkTagInfo(dapSystemTag, true);
        return flag ? ResultBean.ok(dapSystemTagService.save(dapSystemTag)) : ResultBean.error(String.format("当前标签分组存在%s标签", dapSystemTag.getName()));

    }

    // ok
    @BmPermission(value = "system:tags:modify", name = "编辑")
    @PostMapping("tags/update")
    @ApiOperation(value = "修改标签")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = Boolean.class)})
    @OperateLog(type = OperateType.UPDATE, moduleName = ModuleObject.SYSTEM)
    public ResultBean<Boolean> updateTags (@RequestBody @Valid DapSystemTag dapSystemTag){

        Boolean flag = dapSystemTagService.checkTagInfo(dapSystemTag, false);
        return flag ? ResultBean.ok(dapSystemTagService.updateById(dapSystemTag)) :  ResultBean.error(String.format("当前标签分组存在%s标签", dapSystemTag.getName()));

    }

    @BmPermission(value = "system:tags:delete", name = "删除")
    @DeleteMapping("tags/delete")
    @ApiOperation(value = "删除标签")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = ResultBean.class)})
    @OperateLog(type = OperateType.DELETE, moduleName = ModuleObject.SYSTEM)
    public ResultBean<Object> deleteTags (@RequestBody @Valid List<String> ids){

        List<DapSystemTag> tagList = new ArrayList<>();
        boolean isDel = true;
        for(String id : ids){
            // 需要进行判断，是否有其他模型或模型表引用了该标签
            ResultBean<List<DapDataModelSystemTagMiddle>> listByTagId = dapDataModelSystemTagMiddleService.getTagMiddleList(id);
            // 为空则没被引用，可删除
            if(listByTagId.getContent().isEmpty()){
                DapSystemTag dapSystemTag = new DapSystemTag();
                dapSystemTag.setId(id);
                dapSystemTag.setBmStatus(BmStatus.DELETE);
                tagList.add(dapSystemTag);
            }else{
                isDel = false;
            }
        };
        return isDel ? ResultBean.ok(dapSystemTagService.updateBatchById(tagList)) : ResultBean.error( "标签被被引用，无法删除！");
    }

    @BmPermission(value = "system:tags:list", name = "标签分组列表")
    @GetMapping("tag/groups")
    @ApiOperation(value = "获取标签分组列表")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = ResultBean.class)})
    public ResultBean<List<DapSystemTagGroup>> selectTagsGroupList(){

        List<DapSystemTagGroup> dapSystemTagGroups = dapSystemTagGroupService.getBaseMapper().selectList(new LambdaQueryWrapper<DapSystemTagGroup>()
                .eq(DapSystemTagGroup::getBmStatus, BmStatus.ON.getCode()));
        return ResultBean.ok(dapSystemTagGroups);
    }

    @BmPermission(value = "system:tags:add", name = "新增标签分组")
    @PostMapping("tag/group/add")
    @ApiOperation(value = "新增或修改标签分组")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = ResultBean.class)})
    public ResultBean<Boolean> addTagGroup(@ApiParam(value ="标签分组名称") @RequestParam("name")
                                               @Size(max = 12, message = "标签分组长度不能超过12") String name,
                                           @ApiParam(value ="标签id") @RequestParam(value = "id", required = false) String id ){

        Boolean flag = dapSystemTagGroupService.checkGroupInfo(name, id);
        if(flag){
            DapSystemTagGroup dapSystemTagGroup = new DapSystemTagGroup();
            dapSystemTagGroup.setTagGroupName(name);
            dapSystemTagGroup.setId(id);
            return ResultBean.ok( dapSystemTagGroupService.saveOrUpdate(dapSystemTagGroup));
        }
        return ResultBean.error(String.format("标签分组%s已存在", name));
    }

    @BmPermission(value = "system:tags:delete", name = "删除标签分组")
    @DeleteMapping("tag/group/delete")
    @ApiOperation(value = "删除标签分组")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = ResultBean.class)})
    public ResultBean<Boolean> deleteTagGroup(@ApiParam(value ="标签分组id") @RequestParam("id") String id){

        String message = dapSystemTagGroupService.checkGroupIsUse(id);
        if(message == null){
            dapSystemTagGroupService.getBaseMapper().deleteById(id);
            return ResultBean.ok(true);
        }
        return ResultBean.error(String.format("当前分组被标签%s绑定，不允许删除", message));
    }

    /**
     * 获取系统信息，带模糊搜索
     * @param pageSize
     * @param pageNum
     * @param sysName
     * @return
     */
    @BmPermission(value = "system:info:list", name = "列表查询")
    @GetMapping("sysInfo/pageList")
    @ApiOperation(value = "获取系统信息，带模糊搜索")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = SystemInfoDto.class)})
    public ResultBean<IPage<SystemInfoDto>> selectSystemInfoPage(@ApiParam(value = "每页显示的数量", example = "0") @RequestParam Integer pageSize,
                                                                 @ApiParam(value = "当前页码数", example = "0") @RequestParam Integer pageNum,
                                                                 @ApiParam("系统名称") @RequestParam(required = false) String sysName){

        IPage<SystemInfoDto> sysPageList = dapSystemInfoService.getSysPageList(pageSize, pageNum, sysName);
        return ResultBean.ok(sysPageList);
    }

    @BmPermission(value = "system:info:add", name = "新增")
    @PostMapping("sysInfo/insert")
    @ApiOperation(value = "新增系统信息")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = Boolean.class)})
    @OperateLog(type = OperateType.INSERT, moduleName = ModuleObject.SYSTEM)
    public ResultBean<Boolean> insertSysInfo (@Valid @RequestBody SystemInfoVo systemInfoVo){


        ResultBean<Boolean> booleanResultBean = dapSystemInfoService.insertSystem(systemInfoVo);
        return booleanResultBean;
    }

    @BmPermission(value = "system:info:detail", name = "详情")
    @GetMapping("sysInfo/single/detail")
    @ApiOperation(value = "查询单个系统的详细信息")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = SysInfoDto.class)})
    public ResultBean<SysInfoDto> getSysInfo (@RequestParam @ApiParam("系统id") String sysId){

        SysInfoDto sysInfo = dapSystemInfoService.getSysInfo(sysId);
        // 查询系统是否被模型引用
//        ResultBean<List<DapDataModel>> models = dapDataModelService.getModels(sysId);
        // 默认可编辑
//        Boolean isModify = models.getContent().isEmpty() ? false : true;
        return ResultBean.ok(sysInfo).addMoreData("isModify", false);
    }

    @BmPermission(value = "", name = "", ignore = true)
    @GetMapping("sysInfo/detail")
    @ApiOperation(value = "系统信息详情")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = DapSystemDatasource.class)})
    public ResultBean<List<DapSystemDatasource>> sysInfoDetail (@RequestParam @ApiParam("系统id") String sysId){

        // 查询该系统引用的数据源信息
        List<DapSystemDatasource> allDatasource = dapSystemDatasourceService.getAllDatasource(sysId);
        return ResultBean.ok(allDatasource);
    }

    @BmPermission(value = "system:info:delete", name = "删除")
    @DeleteMapping("sysInfo/delete")
    @ApiOperation(value = "删除系统")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = Boolean.class)})
    @OperateLog(type = OperateType.DELETE, moduleName = ModuleObject.SYSTEM)
    public ResultBean<Boolean> sysInfoDelete (@RequestBody @Valid List<String> ids){

        List<DapSystemInfo> dapSystemInfos = dapSystemInfoService.getBaseMapper().selectBatchIds(ids);
        ResultBean<Boolean> booleanResultBean = dapSystemInfoService.deleteSystem(dapSystemInfos);
        return booleanResultBean;
    }

    @BmPermission(value = "system:info:modify", name = "编辑")
    @PostMapping("sysInfo/update")
    @ApiOperation(value = "修改系统信息")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = Boolean.class)})
    @OperateLog(type = OperateType.UPDATE, moduleName = ModuleObject.SYSTEM)
    public ResultBean<Boolean> sysInfoUpdate (@Valid @RequestBody SystemInfoVo systemInfoVo){

        // 修该系统信息
        ResultBean<Boolean> booleanResultBean = dapSystemInfoService.updateSystem(systemInfoVo);
        return booleanResultBean;
    }

    @BmPermission(value = "", name = "", ignore = true)
    @GetMapping("/dataSource/list")
    @ApiOperation(value = "获取系统数据源列表数据（用于指标标准中）")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = DapSystemDatasource.class)})
    public ResultBean<List<DapSystemDatasource>> indexGetSystemDataSources() {
        List<DapSystemDatasource> list = dapSystemDatasourceService.
                list(Wrappers.<DapSystemDatasource>lambdaQuery().
                        eq(BaseModel::getBmStatus, BmStatus.ON)
                        .orderByDesc(BaseModel::getUpdateTime));
        return ResultBean.ok(list);
    }

    @BmPermission(value = "", name = "", ignore = true)
    @GetMapping("/system/list")
    @ApiOperation(value = "获取系统数据源列表数据（用于指标标准中）")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = DapSystemInfo.class)})
    public ResultBean<List<DapSystemInfo>> indexGetSystems() {
        List<DapSystemInfo> list = dapSystemInfoService.list(Wrappers.<DapSystemInfo>lambdaQuery().
                        eq(BaseModel::getBmStatus, BmStatus.ON)
                        .orderByDesc(BaseModel::getUpdateTime));
        return ResultBean.ok(list);
    }

    /**
     * 从其他模型导入进
     * 当前模型的系统列表
     */
    @BmPermission(value = "", name = "", ignore = true)
    @GetMapping("import/system/list")
    @ApiOperation(value = "获取系统数据源列表数据")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = DapSystemInfo.class)})
    public ResultBean<List<DapSystemInfo>> importSystemList(){

        // 查询所有的系统信息
        List<DapSystemInfo> systemInfos = dapSystemInfoService.list(Wrappers.<DapSystemInfo>lambdaQuery()
                        .eq(BaseModel::getBmStatus, BmStatus.ON));
        return ResultBean.ok(systemInfos);
    }

    @BmPermission(value = "", name = "", ignore = true)
    @GetMapping("mysql/system")
    @ApiOperation(value = "获取关联mysql的系统")
    @ApiResponses(value = {@ApiResponse(code = 500, message = "错误原因信息", response = String.class),
            @ApiResponse(code = 200, message = "ok", responseContainer = "List", response = DapSystemInfo.class)})
    public ResultBean<List<DapSystemInfo>> mysqlSystemList(){

        // 查询mysql的数据源
        List<DapSystemDatasource> list = dapSystemDatasourceService.list(Wrappers.<DapSystemDatasource>lambdaQuery().eq(DapSystemDatasource::getBmStatus, BmStatus.ON.getCode())
                .eq(DapSystemDatasource::getDatabaseType, DatabaseType.MYSQL.getCode()).ne(DapSystemDatasource::getSystemInfoId, "0"));
        List<String> systemIds = list.stream().map(DapSystemDatasource::getSystemInfoId).collect(Collectors.toList());
        List<DapSystemInfo> systemInfos = dapSystemInfoService.list(Wrappers.<DapSystemInfo>lambdaQuery().in(DapSystemInfo::getId, systemIds));
        return ResultBean.ok(systemInfos);
    }

    @BmPermission(value = "", name = "", ignore = true)
    @GetMapping("user/list")
    @ApiOperation(value = "获取关用户的列表信息")
    @ApiResponses(value = {@ApiResponse(code = 500, message = "错误原因信息", response = String.class),
            @ApiResponse(code = 200, message = "ok", responseContainer = "List", response = UserDto.class)})
    public ResultBean<List<UserDto>> getUserList(@RequestParam( value = "tecName", required = false)
                                                     @ApiParam("技术负责人名称") String tecName){

        String token = UserInfoHolder.getUserInfo().get().getToken();
        ResultBean<List<UserDto>> listResultBean = iDompService.matchUserInfos(token, tecName, null);
        return listResultBean;
    }

    @BmPermission(value = "system:info:list", name = "所有系统信息")
    @GetMapping("list")
    @ApiOperation(value = "获取所有系统信息")
    @ApiResponses(value = {@ApiResponse(code = 500, message = "错误原因信息", response = String.class),
            @ApiResponse(code = 200, message = "ok", responseContainer = "List", response = DapSystemInfo.class)})
    public ResultBean<List<DapSystemInfo>> getSystemList(){

        LambdaQueryWrapper<DapSystemInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DapSystemInfo::getBmStatus, BmStatus.ON.getCode());
        List<DapSystemInfo> dapSystemInfos = dapSystemInfoService.getBaseMapper().selectList(wrapper);
        return ResultBean.ok(dapSystemInfos);
    }

}
